﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Timers;
using Timer=System.Timers.Timer;

namespace CARMSBusiness
{
    public enum Priority
    {
        Low = 0,
        Medium = 1,
        High = 2
    }

    public abstract class TaskBase
    {
        private Timer timer;

        /// <summary>
        /// 获取计划中任务执行的间隔时间（包含任务的执行时间）。单位为毫秒。
        /// </summary>
        public double Interval { get; private set; }

        /// <summary>
        /// 获取任务计划是否已经被停止。
        /// </summary>
        public bool Stopped { get; private set; }

        /// <summary>
        /// 获取任务计划的优先级。
        /// </summary>
        public Priority Priority { get; private set; }

        /// <summary>
        /// 获取最后一次任务开始执行的时间。
        /// </summary>
        public DateTime LastRunTime { get; private set; }

        /// <summary>
        /// 获取最后一次任务是否执行成功。
        /// </summary>
        public bool IsLastRunSuccessful { get; private set; }

        /// <summary>
        /// 获取当前的计划是否有任务正在执行。
        /// </summary>
        public bool IsRunning { get; private set; }

        /// <summary>
        /// 获取任务计划的名称。
        /// </summary>
        public string Name { get; private set; }

        public bool Initialized { get; private set; }

        /// <summary>
        /// 启动任务计划。
        /// </summary>
        public void Start()
        {
            // 如果已经初始化并且启动则不需要再次启动
            if (!Stopped && Initialized)
            {
                return;
            }
            // 第一次启动计划时，创建新的Timer
            if (timer == null)
            {
                timer = new Timer(Interval);
                timer.Elapsed += TimerElapsed;
            }
            timer.Enabled = true;
            timer.Start();
            Stopped = false;
            OnStart();
            // 在开始启动计划时执行第一次任务.
            StartTask();
        }

        /// <summary>
        /// 停止任务计划，但不会停止当前正在执行的任务。
        /// </summary>
        public void Stop()
        {
            if (Stopped || !Initialized)
            {
                return;
            }
            timer.Stop();
            timer.Enabled = false;
            Stopped = true;
            OnStop();
        }

        internal void Initialize(string name, double interval, Priority priority)
        {
            Name = name;
            Interval = interval;
            Priority = priority;
            Initialize();
        }

        /// <summary>
        /// 初始化任务计划。
        /// </summary>
        public virtual void Initialize()
        {
            if (Initialized)
            {
                return;
            }
            // 初始化时默认启动计划。
            Start();
            Initialized = true;
        }

        private void TimerElapsed(object sender, ElapsedEventArgs e)
        {
            if (!IsRunning)
                StartTask();
        }

        private void StartTask()
        {
            // 只有在计划没有停止并且计划中没有任务执行的情况下才启动新的任务。
            // 如果任务执行时间比较长，在执行的过程中调用Stop方法之后
            // 再次调用Start方法会出现 IsRunning=true 的情况。
            if (!Stopped && !IsRunning)
            {
                new Thread(Execute).Start();
            }
        }

        private void Execute()
        {
            try
            {
                IsRunning = true;
                LastRunTime = DateTime.Now;
                Run();
                IsLastRunSuccessful = true;
            }
            catch
            {
                // Todo: 记录异常日志
                IsLastRunSuccessful = false;
            }
            finally
            {
                IsRunning = false;
            }
        }

        protected virtual void OnStop()
        {
        }

        protected virtual void OnStart()
        {
        }

        /// <summary>
        /// 执行任务。
        /// </summary>
        public abstract void Run();
    }
}
